#   Copyright 2006 Jerome Lacoste (jerome@coffeebreaks.org)
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
class ProjectsController < ApplicationController

  before_filter :authorize

  # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
  verify :method => :post, :only => [ :destroy, :create, :update ],
         :redirect_to => { :action => :list }

  def list
    client_id = params[:id]
    # primary check
    if (client_id)
      @client = find_client(params[:id])
      return unless @client
    end

    # deal with the project form
#    if request.post?
#      update_project_and_assignees
#      if @project.save
#        flash[:notice] = 'Project was successfully created.'
#        if @client
#          redirect_to :action => 'list', :id => @client
#        else
#          redirect_to :action => 'list'
#        end
#      else
#        # form filling is invalid...
#        #if @client
#        #  render :action => 'list'
#        #else
#        #  render :action => 'list_all'
#        #end
#      end
#    else
      init_new_project
      @users = User.find(:all)
      # prepare things used for viewing
      @sorter = SortingHelper::Sorter.new self, %w(short name), params['sort'], params['order'], 'name', 'ASC'
      if (@client)
        @project_pages, @projects = pagination Project.find_all_by_client_id(@client.id, @sorter.to_sql)
      else
#        @project_pages, @projects = pagination Project.find_assigned_to_user(session[:user_id], @sorter.to_sql)
        @project_pages, @projects = pagination Project.find_owned_by_user(session[:user_id], @sorter.to_sql)
        render :action => 'list_all'
      end
#    end
  end

  # when called with an +client_id+ as argument lists the client specific's projects
  # otherwise lists all projects
  # also prepares for creating adding new project
#  def list2
#    client_id = params[:id]
#    init_new_project(client_id)
#    @sorter = SortingHelper::Sorter.new self, %w(short name), params['sort'], params['order'], 'name', 'ASC'
#    if (client_id)
#      # @client = find_client(params[:id])
#      return unless @client
#      # @client.projects
#      @project_pages, @projects = pagination Project.find_all_by_client_id(@client.id, @sorter.to_sql)
#    else
#      # User.find(session[:user_id]).assigned_projects
#      # FIXME sorting doesn't work here
#      @project_pages, @projects = pagination Project.find_user_projects(session[:user_id], @sorter.to_sql)
#      render :action => 'list_all'
#    end
#  end

#  def show
#    @project = Project.find(params[:id])
#    @users = User.find(:all)
#  end

  def new
    client_id = params[:id]
    if (client_id)
      return unless @client = find_client(client_id)
    end
    init_new_project
    @users = User.find(:all)
  end

  def create
    @users = User.find(:all)
    update_project_and_assignees
    if @project.save
      flash[:notice] = 'Project was successfully created.'
      redirect_to :action => 'list', :id => @client
    else
      redirect_to :action => 'list'
    end
  end

  def edit
    update
  end

  def update
    return unless @project = find_project(params[:id])
    @users = User.find(:all)
    if request.get?
      render :action => 'edit'
    else
      if params[:assignee_ids]
        # FIXME can't this be railsified somehow ?? this is ugly (and probably not performant at all)...
        new_assignees = User.find(params[:assignee_ids])
        # remove old ones...
        @project.assignees.each do |old_assignee|
          if ! new_assignees.include? old_assignee
            Assignment.delete_all("user_id = #{old_assignee.id} and project_id = #{@project.id}")
          end
        end
        # add the new ones
        new_assignees.each do |new_assignee|
          # remove those who are not present anymore
          if ! @project.assignees.include? new_assignee
            @project.assignments.create!(:user => new_assignee)
          end
        end
      else
        # puts "cleaning assignees"
        # this won't work because I don't have an id column...
        # @project.assignments.clear 
        Assignment.delete_all("project_id = #{@project.id}")
      end
      @project.assignments(true)
      if @project.update_attributes(params[:project])
        flash[:notice] = 'Project was successfully updated.'
        redirect_to :action => 'edit', :id => @project
      else
        render :action => 'edit'
      end
    end
  end

  def destroy
    project = Project.find(params[:id])
    client_id = project.client_id
    project.destroy
    redirect_to :action => 'list', :id => client_id
  end

  private
  # find the client given its +id+.
  # redirect if no +id+ specified or no client found
  # initialize +@client+ otherwise
  def find_client(id)
    if (id.nil? )
      redirect_to_index("Missing client id")
      return
    end

    begin
      return Client.find(id)
    rescue
      logger.error("Attempt to access invalid client #{id}")
      redirect_to_index("Invalid client")
    end
    nil
  end

  def find_project(id)
    if (id.nil?)
      redirect_to_index("Missing project id")
      return
    end

    begin
      return Project.find(id)
    rescue
      logger.error("Attempt to access invalid project #{id}")
      redirect_to_index("Invalid project")
    end
    nil
  end

  def init_new_project
    @project = Project.new
    if (@client)
      @project.client_id = @client.id
    else
      @owner = User.find(session[:user_id])
    end
  end

  def update_project_and_assignees
    @project = Project.new(params[:project])
    if (! @project.client_id.nil?)
      @client = Client.find(@project.client_id)
      # we will fail in save...
    end
    if params[:assignee_ids]
      new_assignees = User.find(params[:assignee_ids])
      new_assignees.each do |new_assignee|
        if ! @project.assignments.include? new_assignee
          @project.assignments.create!(:user => new_assignee, :project => @project)
        end
      end
    end
  end
end
